// --------------------------------------------------------------------------------------------------------------------
// <copyright file="AzureStorageTableAuthenticationService.cs" company="AzureContrib (Open source library http://azurecontrib.codeplex.com)">
//   Microsoft Public License (Ms-PL)
// </copyright>
// <summary>
//   An <see cref="IAuthenticationService" /> that does nothing with the incoming <see cref="IClaimsPrincipal" />
// </summary>
// --------------------------------------------------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Security.Cryptography.X509Certificates;

using AzureContrib.WindowsAzure.ServiceRuntime;
using AzureContrib.WindowsAzure.StorageClient;

using Microsoft.IdentityModel.Claims;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.StorageClient;

using Thinktecture.IdentityModel.Extensions;

namespace AzureContrib.WindowsAzure.AccessControlService
{
	/// <summary>
	/// An <see cref="IAuthenticationService"/> that checks users against a windows Azure Storage Table.
	/// </summary>
	internal class AzureStorageTableAuthenticationService : IAuthenticationService
	{
		/// <summary>
		/// The data context for where authentication data is stored in Windows Azure Storage.
		/// </summary>
		public const string DataContextName = "AzureContrib.WindowsAzure.AccessControlService.DataContext";

		/// <summary>
		/// The default name of the authentication table in Windows Azure Storage.
		/// </summary>
		public const string AuthenticationTableName = "authenticationservice";

		private readonly ICloudStorageAccountManager cloudStorageAccountManager;

		public const string AuthenticationTableConfigurationName = "AzureContrib.WindowsAzure.AccessControlService.AuthenticationTableName";

		private string tableName;

		private ICloudTableClient cloudTableClient;

		public AzureStorageTableAuthenticationService(ICloudStorageAccountManager cloudStorageAccountManager, IRoleEnvironment roleEnvironment)
		{
			this.cloudStorageAccountManager = cloudStorageAccountManager;

			if (!roleEnvironment.TryGetConfigurationSettingValue(AuthenticationTableConfigurationName, out tableName))
			{
				tableName = AuthenticationTableName;
			}

			CloudTableClient.CreateTableIfNotExist(tableName);
		}

		private ICloudTableClient CloudTableClient
		{
			get
			{
				return cloudTableClient ?? (cloudTableClient = cloudStorageAccountManager.GetCloudTableClient(DataContextName));
			}
		}

		/// <summary>
		/// Will authenticate users coming in to the service
		/// </summary>
		/// <param name="resourceName">The name of the resource to authenticate access to.</param>
		/// <param name="incomingPrincipal">The principal of the user to be authenticated.</param>
		/// <returns>The <paramref name="incomingPrincipal"/>.</returns>
		public IClaimsPrincipal Authenticate(string resourceName, IClaimsPrincipal incomingPrincipal)
		{
			var claimedNameIdentifier = incomingPrincipal.GetClaimValue(Microsoft.IdentityModel.Claims.ClaimTypes.NameIdentifier);
			var claimedIdentityProvider = incomingPrincipal.GetClaimValue(ClaimTypes.IdentityProvider);

			if (!string.IsNullOrWhiteSpace(claimedNameIdentifier) &
					!string.IsNullOrWhiteSpace(claimedIdentityProvider))
			{
				string userID;
				if (TryGetUserId(claimedNameIdentifier, claimedIdentityProvider, out userID))
				{
					IList<Claim> claims = new List<Claim>
						{
							new Claim(ClaimTypes.UserID, userID)
						};
					incomingPrincipal.Identities.Add(new ClaimsIdentity(claims, GetType().FullName));
				}
			}

			return incomingPrincipal;
		}

		private bool TryGetUserId(string claimedNameIdentifier, string claimedIdentityProvider, out string userID)
		{
			//Microsoft.WindowsAzure.StorageClient.CloudTableClient client;
			//Microsoft.WindowsAzure.StorageClient.TableServiceContext tableServiceContext;

			AuthenticationServiceContext authenticationServiceContext = new AuthenticationServiceContext();

			userID = 42.ToString(CultureInfo.InvariantCulture);
			return true;
		}
	}

	/// <summary>
	/// 
	/// </summary>
	internal class AuthenticationServiceContext : TableServiceContext
	{
		public AuthenticationServiceContext(string baseAddress, StorageCredentials credentials)
			: base(baseAddress, credentials)
		{
		}

		public IQueryable<AuthenticationData> Authentications
		{
			get
			{
				return CreateQuery<AuthenticationData>("AuthenticationData");
			}
		}

		//public void AddMessage(string name, string body)
		//{
		//  this.AddObject("Messages", new Message { Name = name, Body = body });
		//  this.SaveChanges();
		//}
	}

	/// <summary>
	/// 
	/// </summary>
	public class AuthenticationData : TableServiceEntity
	{
	}
}